home *** CD-ROM | disk | FTP | other *** search
- #define PBITS 16
- #define BITS PBITS
-
- unsigned char magic_header[] = {
- "\037\235" }; /* 1F 9D */
-
- /* Defines for third byte of header */
- #define BIT_MASK 0x1f
- #define BLOCK_MASK 0x80
- /* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
- a fourth header byte (for expansion).
- */
- #define INIT_BITS 9 /* initial number of bits/code */
-
- #include <stdio.h>
-
- int n_bits; /* number of bits/code */
- int maxbits = BITS; /* user settable max # bits/code */
- long int maxcode; /* maximum code, given n_bits */
- long int maxmaxcode = 1 << BITS; /* should NEVER generate this code */
- # define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
-
- /*
- * One code could conceivably represent (1<<BITS) characters, but
- * to get a code of length N requires an input string of at least
- * N*(N-1)/2 characters. With 5000 chars in the stack, an input
- * file would have to contain a 25Mb string of a single character.
- * This seems unlikely.
- */
- # define MAXSTACK 8000 /* size of output stack */
-
- unsigned short tab_prefix [69001];
- unsigned char tab_suffix[1<<BITS]; /* last char in this entry */
-
- long int free_ent = 0; /* first unused entry */
- int exit_stat = 0;
-
- long int getcode();
-
- /*
- * block compression parameters -- after all codes are used up,
- * and compression rate changes, start over.
- */
- int block_compress = BLOCK_MASK;
- int clear_flg = 0;
- /*
- * the next two codes should not be changed lightly, as they must not
- * lie within the contiguous general code space.
- */
- #define FIRST 257 /* first free entry */
- #define CLEAR 256 /* table clear output code */
-
- main()
- {
- if(maxbits < INIT_BITS) maxbits = INIT_BITS;
- if (maxbits > BITS) maxbits = BITS;
- maxmaxcode = 1 << maxbits;
-
- exit_stat = 0;
- /* Check the magic number */
- if ((getchar() != (magic_header[0] & 0xFF))
- || (getchar() != (magic_header[1] & 0xFF))) {
- fprintf(stderr,"not in compressed format\n");
- exit(1);
- }
- maxbits = getchar(); /* set -b from file */
- block_compress = maxbits & BLOCK_MASK;
- maxbits &= BIT_MASK;
- maxmaxcode = 1 << maxbits;
- if(maxbits > BITS) {
- fprintf(stderr,
- "compressed with %d bits, can only handle %d bits\n",
- maxbits, BITS);
- exit(1);
- }
- decompress();
- exit(exit_stat);
- }
- unsigned char rmask[9] = {
- 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
- decompress() {
- register int stack_top = MAXSTACK;
- register long int code, oldcode, incode;
- register int finchar;
- char stack[MAXSTACK];
-
- /*
- * As above, initialize the first 256 entries in the table.
- */
- maxcode = MAXCODE(n_bits = INIT_BITS);
- for ( code = 255; code >= 0; code-- ) {
- tab_prefix[code] = 0;
- tab_suffix[code] = (unsigned char)code;
- }
- free_ent = ((block_compress) ? FIRST : 256 );
-
- finchar = oldcode = getcode();
- putchar( (char)finchar ); /* first code must be 8 bits = char */
-
- while ( (code = getcode()) != -1 ) {
-
- if ( (code == CLEAR) && block_compress ) {
- for ( code = 255; code > 0; code -= 4 ) {
- tab_prefix [code-3] = 0;
- tab_prefix [code-2] = 0;
- tab_prefix [code-1] = 0;
- tab_prefix [code] = 0;
- }
- clear_flg = 1;
- free_ent = FIRST - 1;
- if ( (code = getcode ()) == -1 ) /* O, untimely death! */
- break;
- }
- incode = code;
- /*
- * Special case for KwKwK string.
- */
- if ( code >= free_ent ) {
- stack[--stack_top] = finchar;
- code = oldcode;
- }
-
- /*
- * Generate output characters in reverse order
- */
- while ( code >= 256 ) {
- stack[--stack_top] = tab_suffix[code];
- code = tab_prefix[code];
- }
- stack[--stack_top] = finchar = tab_suffix[code];
-
- /*
- * And put them out in forward order
- */
- for ( ; stack_top < MAXSTACK; stack_top++ )
- putchar(stack[stack_top]);
- if (ferror(stdout))
- writeerr ( );
- stack_top = MAXSTACK;
-
- /*
- * Generate the new entry.
- */
- if ( (code=free_ent) < maxmaxcode ) {
- tab_prefix[code] = (unsigned short)oldcode;
- tab_suffix[code] = finchar;
- free_ent = code+1;
- }
- /*
- * Remember previous code.
- */
- oldcode = incode;
- }
- fflush( stdout );
- if(ferror(stdout))
- writeerr();
- }
-
-
- /*****************************************************************
- * TAG( getcode )
- *
- * Read one code from the standard input. If EOF, return -1.
- * Inputs:
- * stdin
- * Outputs:
- * code or -1 is returned.
- */
-
- long int
- getcode() {
- /*
- * On the VAX, it is important to have the register declarations
- * in exactly the order given, or the asm will break.
- */
- register long int code;
- static int offset = 0, size = 0;
- static unsigned char buf[BITS];
- register int r_off, bits;
- register unsigned char *bp = buf;
-
- if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
- /*
- * If the next entry will be too big for the current code
- * size, then we must increase the size. This implies reading
- * a new buffer full, too.
- */
- if ( free_ent > maxcode ) {
- n_bits++;
- if ( n_bits == maxbits )
- maxcode = maxmaxcode; /* won't get any bigger now */
- else
- maxcode = MAXCODE(n_bits);
- }
- if ( clear_flg > 0) {
- maxcode = MAXCODE (n_bits = INIT_BITS);
- clear_flg = 0;
- }
- size = fread( buf, 1, n_bits, stdin );
- if ( size <= 0 )
- return -1; /* end of file */
- offset = 0;
- /* Round size down to integral number of codes */
- size = (size << 3) - (n_bits - 1);
- }
- r_off = offset;
- bits = n_bits;
- /*
- * Get to the first byte.
- */
- bp += (r_off >> 3);
- r_off &= 7;
- /* Get first part (low order bits) */
- code = (*bp++ >> r_off);
- bits -= (8 - r_off);
- r_off = 8 - r_off; /* now, offset into code word */
- /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- if ( bits >= 8 ) {
- code |= *bp++ << r_off;
- r_off += 8;
- bits -= 8;
- }
- /* high order bits. */
- code |= (*bp & rmask[bits]) << r_off;
- offset += n_bits;
-
- return code;
- }
- /*****************************************************************
- * TAG( writeerr )
- *
- * Exits with a message. We only check for write errors often enough
- * to avoid a lot of "file system full" messages, not on every write.
- * ferror() check after fflush will catch any others (I trust).
- *
- */
-
- writeerr()
- {
- exit ( 1 );
- }
-